feat(applicationlayer): WAF v3 render + kube-controllers config plumbing#4779
Draft
electricjesus wants to merge 7 commits into
Draft
feat(applicationlayer): WAF v3 render + kube-controllers config plumbing#4779electricjesus wants to merge 7 commits into
electricjesus wants to merge 7 commits into
Conversation
2ac4a1a to
ad421ec
Compare
3 tasks
Adds the WAF v2/v3 admission webhook render path as forward-looking infrastructure. Sibling to the existing WAF v1 (sidecar / ModSecurity) render in pkg/render/applicationlayer/applicationlayer.go, which is untouched. - pkg/common/common.go: GatewayAddonsFeature = "ingress-gateway-addons" constant. Naming is deliberate: the feature gates Tigera-built ADD-ONS (currently the WAF v2/v3 admission webhook), NOT the bare ingress gateway data path. - pkg/render/applicationlayer/gateway_waf.go: WAFAdmissionWebhookComponents returns the 6 objects required for the webhook (Deployment + Service + ServiceAccount + ClusterRole + ClusterRoleBinding + ValidatingWebhookConfiguration). - pkg/render/applicationlayer/gateway_waf_test.go: per-function test. Out of scope for this PR (deferred to follow-ups): - Controller wire-up: invoking the render path requires resolving the webhook cert pair + image references, plus a license fetch. That wire-up depends on a GatewayWAF (or similar) field being added to ApplicationLayerSpec to gate the existing reconcile body. - KubeControllersConfiguration ApplicationLayer field defaulting: depends on a tigera/api version bump after the calico-private side of the design lands. - BFF + frontend module render: belongs to a separate UI epic, not this controller-side scope.
…ONTROLLERS The applicationlayer manager registered by tigera/calico-private#11834 runs WAF / GlobalWAF / Plugin / GlobalPlugin / Validation reconcilers inside the kube-controllers binary on Calico Enterprise variants. End-to- end smoke against a licensed cluster confirmed the binary is otherwise ready; what's missing operator-side is RBAC + the ENABLED_CONTROLLERS entry that turns the controller on. Add to the Enterprise common rule set: * applicationlayer.projectcalico.org WAF{Policy,Plugin,ValidationPolicy} + Global variants (resources, /status, /finalizers). * gateway.networking.k8s.io gateways/httproutes/tcproutes/tlsroutes/ grpcroutes (read+update for targetRef validation, /status for surfaces). * core / events.k8s.io events (create+patch) - controller-runtime Recorder emits events on watched objects via either API group depending on the kubernetes minor; without this, every reconcile that hits Recorder.Eventf is rejected with 'events is forbidden'. Append 'applicationlayer' to the Enterprise enabledControllers list so the controller is constructed at startup; runtime activation is still license-gated via features.IngressGateway in calico-private's lifecycle loop, so absence of a gateway-addons-bearing license is a no-op. Verified end-to-end on seth-calient-master: WAFPolicy reconcile completes with conditions Licensed=True / Accepted=True / Validated=Unknown / Programmed=False (Programmed gates on WASMImage, separate follow-up).
The applicationlayer manager registered by tigera/calico-private#11834 reads WASM_IMAGE from the kube-controllers Deployment env to construct the OCI reference its WAF reconcilers use to program EnvoyExtensionPolicy attachments. Without this env, every reconcile stamps the WAFPolicy with Programmed=False / Reason=WASMUnavailable. Add ComponentCorazaWASM (image 'coraza-wasm', enterpriseVariant, master version) to the operator components map and the EnterpriseImages list so it participates in the standard image-version overrides and hashrelease bumps. Resolve the OCI reference through the existing registry / imagePath / imagePrefix path in kubeControllersComponent's ResolveImages, and emit WASM_IMAGE on the deployment env when the variant is Enterprise. The reconciler tolerates an empty WASM_IMAGE by stamping Programmed=False/WASMUnavailable, so this change is safe to land before calico-private's manager.go starts reading the env (companion commit on PR #11834).
…cation + EEP creation End-to-end smoke surfaced two more permissions the applicationlayer reconcilers need that the prior RBAC commit (f28b241) missed: * secrets + configmaps (cluster-wide, full CRUD): the WAF reconciler replicates WASM_PULL_SECRET from controllerNamespace into each WAFPolicy's namespace so the rendered EnvoyExtensionPolicy can reference it; analogous flow for the WASM_CA_CERT ConfigMap. Without this, reconcile fails with 'secrets is forbidden ... cannot create resource secrets in API group ""'. * gateway.envoyproxy.io/envoyextensionpolicies (cluster-wide, full CRUD): the WAF reconciler emits one EnvoyExtensionPolicy per targetRef to bind the Coraza wasm filter at the gateway / route. Without this, reconcile errors before patching status. Mirrors the resources tigera/calico-private's WAFReconciler/Generator already write to; verified end-to-end against seth-calient-master.
… calico-kube-controllers Companion to commit 38f81fd ("inject WASM_IMAGE env"). The applicationlayer manager registered by tigera/calico-private#11834 also reads WASM_PULL_SECRET and WASM_CA_CERT off its process env: the reconciler replicates the named Secret and ConfigMap from the kube-controllers namespace into each WAFPolicy's namespace before referencing them from the rendered EnvoyExtensionPolicy so the wasm fetcher can pull from a private Tigera registry over its TLS chain. End-to-end smoke on seth-calient-master confirmed Programmed=True only after a manually-crafted GCR pull-secret was attached and WASM_PULL_SECRET was set on the Deployment by hand. With this change, every Enterprise install picks the right values up automatically. Sources: WASM_PULL_SECRET <- first entry of Installation.ImagePullSecrets (the same secret already attached to the Deployment via PodSpec.ImagePullSecrets, so multi-tenant / BYO-registry installs reuse whatever operator already wires up here) WASM_CA_CERT <- certificatemanagement.TrustedCertConfigMapName (the existing tigera-ca-bundle ConfigMap, already mounted on this Deployment via TrustedBundle) The supplementary RBAC commit 6c68d19 already grants secrets+configmaps cluster-wide CRUD; no additional RBAC required. Both env vars stay conditional on the Enterprise variant; Calico OSS does not deploy the applicationlayer manager. The reconciler tolerates empty values by stamping Programmed=False/WASMUnavailable, so this change is safe to land independent of #11834's merge order.
…econcilers The four prior wiring commits (f28b241 ENABLED_CONTROLLERS, ad421ec webhook render, 38f81fd WASM_IMAGE, 6c68d19 RBAC for secret replication + EEP creation) plus the WASM_PULL_SECRET / WASM_CA_CERT emission in the previous commit changed the Enterprise render shape but left the existing test fixtures expecting the pre-applicationlayer deployment. Fix the four broken Enterprise fixtures and extend the standalone case with positive assertions on the reconciler's RBAC + env contract: * ENABLED_CONTROLLERS now includes "applicationlayer" on the Enterprise calico-kube-controllers Deployment (two fixtures) * ClusterRole rule counts move 27 -> 36 (calico) and 25 -> 34 (es) after the 9 applicationlayer-related rules added by f28b241 + 6c68d19 * Standalone Enterprise fixture asserts: - applicationlayer.projectcalico.org rules for waf{policies,plugins, validationpolicies} + global variants (resources, /status, /finalizers) - gateway.networking.k8s.io for gateways/httproutes/tcproutes/tlsroutes/ grpcroutes (read+update + /status) - core/events + events.k8s.io/events (create+patch) so controller-runtime Recorder.Eventf works on either k8s version - core/secrets + configmaps cluster-wide CRUD for cross-namespace replication of pull secrets + CA bundles - gateway.envoyproxy.io/envoyextensionpolicies cluster-wide CRUD - WASM_IMAGE resolved through registry/imagePath/imagePrefix - WASM_PULL_SECRET = first Installation.ImagePullSecrets entry, asserted alongside PodSpec.ImagePullSecrets to lock the single-source-of-truth invariant - WASM_CA_CERT = certificatemanagement.TrustedCertConfigMapName Calico OSS coverage stays exhaustive via the existing ConsistOf on the custom-config fixture; none of the applicationlayer wiring is conditional on anything but the Enterprise variant, so OSS env remains unchanged.
783bcb6 to
3b4ab99
Compare
…ons.waf.state Per the 2026-05-12 design walkthrough on PMREQ-384 (recorded in tigera/designs#25 docs/decisions/2026-05-08.md §1), the WAF v3 (Gateway API add-on) surface on calico-kube-controllers is opt-in via a new field on the existing operator GatewayAPI CR: apiVersion: operator.tigera.io/v1 kind: GatewayAPI metadata: name: default spec: extensions: waf: state: Enabled # default Disabled Default-off semantics: unset Extensions, unset WAF, unset State, and explicit Disabled all leave the WAF surface unrendered. Only an explicit {state: Enabled} flips the gate on. What the gate covers: - enabledControllers: "applicationlayer" entry appended only when gate is on (otherwise kube-controllers does not start the WAF reconcilers). - Coraza-WASM image resolution in ResolveImages. - WASM_IMAGE / WASM_PULL_SECRET / WASM_CA_CERT env vars on the calico-kube-controllers Deployment. - WAF / Gateway-API / EnvoyExtensionPolicy / event / secret-replication ClusterRole rules. API change is operator-only: GatewayAPI lives in the operator's own api/v1 package, not tigera/api or calico-private. No tigera/api sync delay. kube-controllers behavior (license-gated WAFReconciler) is unchanged. Installation controller now reads the GatewayAPI CR via the existing "default" name (NotFound = gate off) and watches it so that toggling the field re-triggers a render.
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Operator-side render for WAF v3 (`Coraza WASM`) admission-webhook integration with `calico-kube-controllers`. Pairs with `tigera/calico-private#11834`. Design: `tigera/designs#25`.
Contents
Relationship to #4821
Test plan
Release Note
```release-note
Add operator render for the WAF v3 (Coraza WASM) admission webhook + plumb
`WASM_IMAGE` / `WASM_PULL_SECRET` / `WASM_CA_CERT` env vars onto
`calico-kube-controllers` for the new `WAFReconciler` (paired with
`tigera/calico-private#11834`). Existing WAF v1 (sidecar / ModSecurity)
render path is untouched.
```
Linked